package frame.utils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import frame.common.Config;
import frame.common.Message;
import frame.exception.FrameException;
import frame.service.IFileUploadService;

/**
 * frame框架提供的文件上传工具， 直接通过在页面中调用就可以使用。 TODO 考虑增加带进度条功能的上传
 * 
 * @author 崔鹏
 * 
 */
@Controller
@RequestMapping("/upload")
public class FileUpload {

	/**
	 * 文件信息保存方式：数据库（非贪婪方式） or 文件名称+数据库（贪婪方式） 默认为非贪婪模式
	 */
//	private String model;
	private String sTag = "_service";
	private String sType = "_simple";

	public FileUpload() {/* 无参数的构造器必须有，不然spring 无法将其加载 */
	}

	/**
	 * 上传单个文件 这个请求的解析使用了SPRING 的URI Template Patterns 方式，目的是更好的将前端传入的参数隐藏起来。
	 * place 所指的参数在配置文件(WEB-INFO/config/app.properties)定义。 place
	 * 还可以包含保存上传文件信息的处理方式 app.properties 文件中关于文件上传配置信息应该以place为key前缀用_分割。 分别为 :
	 * place_dir 表示文件存放的文件系统的位置。 place_sql 表示更新文件信息到数据库的sql或sql名称
	 * 参数MultipartFile file默认使用了@RequestParam 方式进行参数解析
	 * @param file
	 * @return
	 */
	@RequestMapping(value = "/{place}/file", method = RequestMethod.POST)
	@ResponseBody
	public String simpleUpload(@PathVariable String place, MultipartFile file,
			HttpServletRequest request) {
		
		String fileDir = (String) Config.getContextProperty(place);// 获取配置的上传文件保存路径
		
		//获取保存文件可使用的路径
		String path = FrameUtils.getPath(request, fileDir);
		
		String fileName = file.getOriginalFilename();// 上传的文件名字
		File targetFile = new File(path, fileName);

		servicing(place,targetFile);
		
		// 保存上传的文件
		try {
			file.transferTo(targetFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
		String filePath = request.getScheme() + "://" + request.getServerName()
				+ ":" + request.getServerPort() + request.getContextPath()
				+ "/"+fileDir+"/"+fileName;
		return filePath;
	}


	/**
	 * 上传多个文件 这个请求的解析使用了SPRING 的URI Template Patterns 方式，目的是更好的将前端传入的参数隐藏起来。
	 * place 所指的参数在配置文件(WEB-INFO/config/app.properties)定义。 参数MultipartFile
	 * file默认使用了@RequestParam 方式进行参数解析
	 * 
	 * @param file
	 * @return , HttpServletRequest request
	 */
	@RequestMapping(value = "/{place}/files", method = RequestMethod.POST)
	@ResponseBody
	public Message simpleUploads(@PathVariable String place,
			MultipartHttpServletRequest  request) {
		String fileDir = (String) Config.getContextProperty(place);// 获取配置的上传文件保存路径
		
		//获取保存文件可使用的路径
		String path = FrameUtils.getPath(request, fileDir);
		
		List<MultipartFile> files=request.getFiles("files");
		List<File> targetFiles=new ArrayList<File>();
		for (MultipartFile file : files) {
			String fileName = file.getOriginalFilename();// 上传的文件名字
			targetFiles.add(new File(path, fileName));
		}
		servicing(place,targetFiles.toArray(new File[0]));
		// 循环保存上传的文件
		try {
			for (int i = files.size()-1; i >=0; i--) {
				files.get(i).transferTo(targetFiles.get(i));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return Message.OK;//操作成功了
	}
	
	/*
	 * 提供服务，根据入参判断是否需要调用服务层，如果需要则调用，否则什么也不做。
	 */
	private void servicing(String place,File...files){
		// 是否为简单上传模式，如果是，则可以不用调用服务层对象，否则必须有服务层对象，这个配置是必须的
		Object isSimple = Config.getContextProperty(place + this.sType);
		if (isSimple == null) {
			throw new FrameException();
		}
		if("true".equalsIgnoreCase((String) isSimple)){
			// 通过spring 获取service的bean执行响应的服务。
			// 先操调用文件上传服务，如果服务层报错，则回滚，文件也不会保存到服务器上
			Object serName = Config.getContextProperty(place + this.sTag);
			IFileUploadService f = null;
			// 依据不同的策略获取服务对象
			if (serName == null) {
				f = (IFileUploadService) SpringUtils.getBean(place);
			} else {
				f = (IFileUploadService) SpringUtils.getBean((String) serName);
			}
			f.updateFileInfo(files);// 执行服务类
		}
		// 上传服务执行完成后，检测保存文件的目录是否存在，如果不存在则创建
		String dir=files[0].getParent();
		File path=new File(dir);
		
		if (!path.exists()) {
//			path.mkdirs();
			System.out.println(path.mkdirs());
//			File dir=new File(files[0].getParent());
//			dir.mkdirs();
		}
	}

//	public void setModel(String model) {
//		this.model = model;
//	}

}
